package com.huilian.iotbox.client.service.impl;

import com.alibaba.fastjson.JSON;
import com.huilian.iotbox.client.dao.OrderRefundDao;
import com.huilian.iotbox.client.service.*;
import com.huilian.iotbox.data.common.RedisKey;
import com.huilian.iotbox.data.common.ServerResponse;
import com.huilian.iotbox.data.dto.OrderDto;
import com.huilian.iotbox.data.dto.OrderRefundDto;
import com.huilian.iotbox.data.enums.*;
import com.huilian.iotbox.data.po.ConsumeRecord;
import com.huilian.iotbox.data.po.Order;
import com.huilian.iotbox.data.po.OrderCommission;
import com.huilian.iotbox.data.service.CommodityPurchaseRestrictionRecordCommonService;
import com.huilian.iotbox.data.service.ErrorLogCommonService;
import com.huilian.iotbox.data.utils.SciCalUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * @author 谢洛涛
 * @date 2021/7/15 16:11
 */
@Service
@Slf4j
public class OrderRefundServiceImpl implements OrderRefundService {

    @Autowired
    private OrderService orderService;
    @Autowired
    private OrderRefundDao orderRefundDao;
    @Autowired
    private ErrorLogCommonService errorLogCommonService;
    @Autowired
    private OrderCommissionService orderCommissionService;
    @Autowired
    private RedisTemplate<String, Serializable> redisCacheTemplate;
    @Autowired
    private CommodityPurchaseRestrictionRecordCommonService commodityPurchaseRestrictionRecordCommonService;

    /**
     * 添加退款记录
     */
    @Override
    public void insertRefundOrder(OrderRefundDto orderRefundDto) {
        log.info("添加退款订单前的参数有{}", JSON.toJSONString(orderRefundDto));
        orderRefundDto.setRefundStatus(RefundStatusEnum.REFUNDING.getCode());
        OrderRefundDto item = new OrderRefundDto();
        try {
            item = orderRefundDao.getRefundOrderByOutradeNo(orderRefundDto.getOutTradeNo());
        } catch (Exception e) {
            errorLogCommonService.writerInfoException("退款异常", orderRefundDto, e);
            e.printStackTrace();
        }

        try {
            // 插入退款记录
            orderRefundDto.setOrderId(item.getOrderId());  //原订单orderId
            orderRefundDto.setRefundAmount(orderRefundDto.getRefundAmount());
            orderRefundDto.setBalance(SciCalUtils.sciCalToBD(item.getBalance().subtract(orderRefundDto.getRefundAmount()), 2));
            orderRefundDto.setPayCompanyCode(orderRefundDto.getPayCompanyCode());
            orderRefundDto.setDeviceNo(item.getDeviceNo());
            orderRefundDao.insert(orderRefundDto);
        } catch (Exception e) {
            e.printStackTrace();
            errorLogCommonService.writerInfoException("退款订单入库出错", orderRefundDto, e);
        }

        try {
            //将退款订单插入到redis中
            redisCacheTemplate.opsForValue().set(RedisKey.ORDER_REFUND_ + orderRefundDto.getOutRefundNo(), orderRefundDto, 10, TimeUnit.DAYS);
        } catch (Exception e) {
            errorLogCommonService.writerInfoException("退款订单信息插入redis出错", orderRefundDto, e);
            e.printStackTrace();
        }

        try {
            //判断是否是隔天退款，如果是隔天退款的话，订单已经结算打款，所以订单我们不再做处理，copy一条订单到今天 , 分润再订
            Integer difDay = orderRefundDao.checkOrderAndRefundDateDif(orderRefundDto);
            if (difDay >= 1) {
                OrderDto order = orderService.getById(Long.valueOf(item.getOrderId()));
                order.setOutTradeNo("隔天退单-" + order.getOutTradeNo() + "-" + (new Random().nextInt(90) + 10));
                //退款金额
                BigDecimal refundAmount = orderRefundDto.getRefundAmount();
                //订单状态修改为 退款中
                order.setStatus(OrderStatusEnum.REFUNDING.getCode());
                //交易总金额
                order.setTotalAmount(SciCalUtils.sciCalToBD(BigDecimal.ZERO.subtract(refundAmount), 2));
                //申请退款金额
                order.setRefundTotalAmount(SciCalUtils.sciCalToBD(refundAmount, 2));
                order.setRefundType(RefunTypeEnum.THE_NEXT_DAY_A_REFUND.getCode());
                //结算金额
                order.setSettlementMoney(SciCalUtils.sciCalToBD(BigDecimal.ZERO.subtract(orderRefundDto.getRefundAmount()), 2));
                order.setSaleCoin(0 - order.getSaleCoin());
                order.setGiveCoin(0 - order.getGiveCoin());
                order.setTotalCoin(0 - order.getTotalCoin());
                order.setRechargeAfterBalance(0);
                order.setRechargeBeforeBalance(0);
                //手续费
                order.setHandlingCharge(BigDecimal.ZERO);
                order.setStmtStatus(0);
                //清除支付完成时间
                order.setGmtPayment(null);
                orderService.add(order);
                orderRefundDto.setOrderId(order.getId());  //新隔天退款订单orderId，用于退款查询刷新新订单状态
                orderRefundDao.updateOrderRefund(orderRefundDto);
            } else {
                OrderDto order = new OrderDto();
                order.setId(Long.valueOf(orderRefundDto.getOrderId()));
                order.setStatus(OrderStatusEnum.REFUNDING.getCode());
                order.setRefundType(RefunTypeEnum.ON_THE_DAY_OF_THE_REFUND.getCode());
                orderService.updateStatusById(order);
            }

        } catch (Exception e) {
            errorLogCommonService.writerInfoException("退款订单处理出错", orderRefundDto, e);
            e.printStackTrace();
        }
    }


    @Override
    public void updateRefundOrder(OrderRefundDto orderRefundDto) throws Exception {
        OrderRefundDto item = orderRefundDao.getInfoByOutTradeNo(String.valueOf(orderRefundDto.getOutRefundNo()));
        if (item == null) {
            errorLogCommonService.writerInfoErrorLog("退款订单查询为空", item);
            return;
        }

        //订单为退款中表示未处理
        if (RefundStatusEnum.REFUNDING.getCode().equals(item.getRefundStatus())) {
            item.setRefundStatus("succ".equals(orderRefundDto.getTradeStatus()) ? RefundStatusEnum.SUCC.getCode() : RefundStatusEnum.FAIL.getCode());
            item.setGmtRefundment(orderRefundDto.getGmtRefundment() == null ? null : orderRefundDto.getGmtRefundment());
            item.setFailReason(orderRefundDto.getFailReason());
            //修改退款状态
            orderRefundDao.updateOrderRefund(item);
            //修改订单状态
            OrderDto order = new OrderDto();
            order.setId(item.getOrderId());    //新隔天退款订单orderId
            order = orderService.getById(order.getId());
            //取得原订单数据 退款会生成订单  原订单也要有数据
            Order oldOrder = null;
            if (order.getTotalAmount().compareTo(BigDecimal.ZERO) < 0) {
                oldOrder = orderService.findOldOrder(item.getOrderId());
            }
            if ("succ".equals(orderRefundDto.getTradeStatus())) {
//                order.setGmtPayment(orderRefundDto.getGmtRefundment() == null ? null : orderRefundDto.getGmtRefundment());
                //余额为零 订单状态为全额退款 否则为部分退款
                if (item.getBalance().compareTo(BigDecimal.ZERO) > 0) {
                    order.setStatus(OrderStatusEnum.PART_REFUND.getCode());
                } else {
                    order.setStatus(OrderStatusEnum.FULL_FERUND.getCode());
                }
                if (order.getTotalAmount().compareTo(BigDecimal.ZERO) < 0) {
                    //隔天退款
                    try {
                        //退款的订单重新计算分润
                        List<OrderCommission> commissionList = orderCommissionService.findByOrderId(oldOrder.getId());
                        for (OrderCommission commission : commissionList) {
                            commission.setOrderId(order.getId());
                            commission.setCommissionTotal(BigDecimal.ZERO.subtract(commission.getCommissionTotal()));
                            commission.setLowerCommission(BigDecimal.ZERO.subtract(commission.getLowerCommission()));
                            commission.setRealCommission(BigDecimal.ZERO.subtract(commission.getRealCommission()));
                            orderCommissionService.insert(commission);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        errorLogCommonService.writerInfoException("隔天退款重算分润出错", orderRefundDto, e);
                    }

                    try {

                    } catch (Exception e) {
                        e.printStackTrace();
                        log.error("隔天退款成功，套餐佣金处理出错:{}", e);
                        errorLogCommonService.writerInfoException("隔天退款成功，套餐佣金处理出错", oldOrder, e);
                    }

                } else {
                    //当天退款
                    try {
                        //删除分润重新计算
                        orderCommissionService.deleteByOrderId(order.getId());
                        order.setTotalAmount(item.getBalance());
                        orderService.orderHandlingCharge(order);
                    } catch (Exception e) {
                        e.printStackTrace();
                        errorLogCommonService.writerInfoException("退款重算分润出错", orderRefundDto, e);
                    }
                }
                orderService.updateStatusById(order);
                // 修改对应的投币状态
                ConsumeRecord consumeRecord = new ConsumeRecord();
                if (order.getTotalAmount().compareTo(BigDecimal.ZERO) < 0) {
                    consumeRecord.setOrderId(oldOrder.getId());
                } else {
                    consumeRecord.setOrderId(order.getId());
                }
                try {
                    // 修改会员限购记录状态
                    ServerResponse serverResponse = commodityPurchaseRestrictionRecordCommonService.updateCommodityPurchaseRestrictionRecordStatusPack(order.getId(), 2);
                    if (!serverResponse.getIsSuccess()) {
                        errorLogCommonService.writerInfoErrorLog("修改会员限购记录状态失败", orderRefundDto);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    errorLogCommonService.writerInfoException("修改会员限购记录状态失败异常", orderRefundDto, e);
                }
            } else {
                try {
                    order.setStatus(OrderStatusEnum.REFUND_FAIL.getCode());
                    BigDecimal balance = item.getBalance().add(new BigDecimal(item.getRefundAmount().toString()));
                    item.setBalance(balance);
                    orderRefundDao.updateOrderRefund(item);
                    orderService.updateStatusById(order);
                    // 修改对应的投币状态
                    ConsumeRecord consumeRecord = new ConsumeRecord();
                    if (order.getTotalAmount().compareTo(BigDecimal.ZERO) < 0) {
                        consumeRecord.setOrderId(oldOrder.getId());
                    } else {
                        consumeRecord.setOrderId(order.getId());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    errorLogCommonService.writerInfoException("退款失败修改状态出错", orderRefundDto, e);
                }
            }
            //redis 集合中移除订单
            redisCacheTemplate.delete(RedisKey.ORDER_REFUND_ + orderRefundDto.getOutRefundNo());
        } else {
            redisCacheTemplate.delete(RedisKey.ORDER_REFUND_ + orderRefundDto.getOutRefundNo());
        }
    }


}
